// gulp 的配置文件
// 0. 导入 gulp 第三方
const gulp = require('gulp')
// 1. 导入一个 gulp-cssmin 第三方, 用于压缩 css 文件
const cssmin = require('gulp-cssmin')
// 1-2. 导入一个 gulp-autoprefixer 第三方, 用于自动添加 css 前缀
const autoprefixer = require('gulp-autoprefixer')
// 2. 导入一个 gulp-sass 第三方, 用于转码 sass 文件
const sass = require('gulp-sass')(require('sass'))
// 3. 导入一个 gulp-uglify 第三方, 用于压缩 js 文件
const uglify = require('gulp-uglify')
// 3-2. 导入一个 gulp-babel 第三方, 用于转码 ES6
const babel = require('gulp-babel')
// 4. 导入一个 gulp-htmlmin 第三方, 用于压缩 html 文件
const htmlmin = require('gulp-htmlmin')
// 4-2. 导入一个 gulp-file-include 第三方, 用于进行 html 组件组装
const fileInclude = require('gulp-file-include')
// 5. 导入一个 del 第三方, 用于删除文件夹使用
const del = require('del')
// 6. 导入一个 gulp-webserver 第三方, 用于开启服务器显示页面
const server = require('gulp-webserver')

/*
  gulp 打包的每一种文件打包规则都不太一样
    + 每一种文件我们书写一个打包任务函数
    + 最终执行这个任务函数, 来打包该文件
    + 当你导出文件以后, 如何进行打包操作
      => 打开命令行, 切换目录到 gulpfile.js 文件所在的目录(项目根目录)
      => 输入指令: $ gulp 任务名称
      => 就会利用全局 gulp 工具去执行该任务

  gulp 的一些方法
    1. gulp.src()
      => 查找需要打包的源文件
    2. gulp.dest()
      => 把打包好的文件存放在指定目录
*/

// 1. 书写打包 css 文件
// 1-1. 准备一个打包 css 文件的任务函数
// 如何压缩 css 文件
// 需要依赖一个叫做 gulp-cssmin 的第三方
// 导入以后得到一个函数, 直接调用即可
// 1-2. 打包 css 文件自动添加前缀
// 需要依赖一个叫做 gulp-autoprefixer 的第三方
// 导入以后得到一个函数, 直接调用传递一个参数即可
const cssHandler = () => {
  // 依赖 gulp 内提供的方法进行书写
  return gulp
    .src('./src/css/*.css') // 作用: 找到需要打包的源文件
    .pipe(autoprefixer()) // 本环节进行自动添加前缀
    .pipe(cssmin()) // pipe 推到下一个环节, 本环节进行压缩操作
    .pipe(gulp.dest('./dist/css/')) // 本环节进行存放压缩完毕的代码
}

// 2. 书写打包 sass 文件
// 2-1. 准备一个打包 sass 文件的任务函数
// 和 打包 css 的任务流程基本一致
// 只是比打包 css 文件多了一个转码的过程
// 转码: 把 sass 转换成 css
/*
  sass 转码需要用到一个第三方叫做 gulp-sass
    => gulp-sass 这个第三方可以进行 sass 转换 css 的过程
    => 但是他需要依赖一个第三方叫做 sass, 他自己不会下载
    => 我们需要手动下载两个第三方, gulp-sass 和 sass
  注意:
    1. 下载的时候两个第三方, gulp-sass 和 sass
    2. 导入的时候语法不太一样, const sass = require('gulp-sass')(require('sass'))
  导入以后得到的就是一个函数, 直接调用即可
*/
const sassHandler = () => {
  return gulp
    .src('./src/sass/*.scss')
    .pipe(sass()) // 本环节进行转码操作
    .pipe(autoprefixer()) // 本环节进行自动添加前缀
    .pipe(cssmin()) // 本环节进行压缩操作
    .pipe(gulp.dest('./dist/sass/')) // 本环节进行存放压缩完毕的代码
}

// 3. 书写打包 js 文件
// 3-1. 准备一个打包 js 文件的任务函数
// 压缩 js 文件需要用到一个第三方叫做 gulp-uglify
// 3-2. 需要把 es6 转换成 es5
/*
  ES6 转换 ES5 语法需要用到一个第三方, 叫做 gulp-babel
    + gulp-babel 需要依赖另外两个第三方, 自己不会下载
      => @babel/core
      => @babel/preset-env
    + 导入以后, 就是一个函数, 使用需要传递参数
      => babel({ presets: [ '@babel/preset-env' ] })
*/
const jsHandler = () => {
  return gulp
    .src('./src/js/*.js')
    .pipe(babel({ presets: [ '@babel/preset-env' ] })) // 本环节进行 ES6 转 ES5
    .pipe(uglify()) // 本环节进行压缩操作
    .pipe(gulp.dest('./dist/js/')) // 本环节进行存放压缩完毕的代码
}

// 4. 书写打包 html 文件
// 4-1. 准备一个打包 html 文件的任务函数
// 压缩 html 文件需要用到一个第三方叫做 gulp-htmlmin
// 下载导入以后就是一个函数, 直接调用传递参数即可
// 4-2. 打包 html 文件组件(了解)
/*
  需要让 html 和 我们自己设计的组件进行组装
    + 组装完毕以后, 在进行压缩操作
  html 组件组装需要用到一个第三方叫做 gulp-file-include
    + 导入以后是一个函数, 调用的时候传递参数即可
    + 配置完毕以后, 就可以在你的 html 文件内使用 自定义标识符去导入指定内容了
*/
const htmlHandler = () => {
  return gulp
    .src('./src/views/*.html')
    .pipe(fileInclude({ // 本环节把组件全部组装完毕
      basepath: './src/components/', // 你存放组件的目录
      prefix: '@-@', // 你自定义的一个标识符, 用于将来在 html 文件内使用的
    }))
    .pipe(htmlmin({ // 本环节进行压缩操作
      collapseWhitespace: true, // 删除空白
      collapseBooleanAttributes: true, // 去除布尔类型属性
      removeAttributeQuotes: true, // 移除双引号
      removeComments: true, // 移除注释
      removeEmptyAttributes: true, // 移除空属性
      removeScriptTypeAttributes: true, // 移除 script 标签的默认 type 属性
      removeStyleLinkTypeAttributes: true, // 移除 style 和 link 标签的 type 属性
      minifyCSS: true, // 压缩内嵌式 css 代码
      minifyJS: true, // 压缩内嵌式 js 代码
    }))
    .pipe(gulp.dest('./dist/views')) // 本环节进行存放压缩完毕的代码
}

// 5. 书写打包 图片 文件
// 5-1. 准备一个打包 图片 文件的任务函数
// 打包 图片文件 需要用到一个第三方叫做 gulp-imagemin
// 导入以后, 就是一个函数, 直接使用
// const imagemin = require('gulp-imagemin')
const imgHandler = () => {
  return gulp
    .src('./src/images/**.*')
    // .pipe() // 本环节进行压缩操作
    .pipe(gulp.dest('./dist/images/')) // 本环节进行存放压缩完毕的代码
}

// 6. 书写转移 若干文件
// 有些内容不需要我们进行打包和压缩, 只要直接转移就好了
// audio video font ...
const videoHandler = () => {
  return gulp
    .src('./src/videos/**.*')
    .pipe(gulp.dest('./dist/videos/'))
}

const audioHandler = () => {
  return gulp
    .src('./src/audios/**.*')
    .pipe(gulp.dest('./dist/audios/'))
}

const fontHandler = () => {
  return gulp
    .src('./src/font/**.*')
    .pipe(gulp.dest('./dist/font/'))
}

// 7. 空过去

// 8. 书写一个 删除 任务
// 作用: 每次完整打包之前, 删除一次 dist 目录, 保证永远都是按照目前的 src 进行的百分百打包操作
// 8-1. 书写一个用于 删除的 任务函数
// 专门用于删除文件夹的第三方叫做 del
const delHandler = () => {
  return del([ './dist/' ])
}

// 9. 配置一个开启服务器任务
// 作用: 开发过程中使用的, 开启一个服务器, 实时显示你的页面
// 需要用到一个第三方叫做 gulp-webserver
/*
  host 可以书写自定义域名, 在自己电脑上使用
    => 找到自己电脑的 hosts 文件
      -> win: 打开我的电脑 C: -> windows -> system32 -> drivers -> etc 有 hosts
      -> MAC: command + shift + g -> 输入 /etc 回车
    => 书写内容
      -> 127.0.0.1          你的自定义域名
*/
const serverHandler = () => {
  return gulp
    .src('./dist/')
    .pipe(server({ // 本环节开启服务器
      host: 'www.guoxiang.com',
      port: 9999,
      open: './views/index.html', // 默认打开哪一个 html 文件
      livereload: true, // 自动刷新页面
      proxies: [ // 在这里配置 gulp 服务器的代理
        { // 每一个对象就是一条代理内容
          source: '/dt', // 代理标识符
          target: 'https://www.duitang.com/napi/blog/list/by_filter_id/', // 代理的目标地址
        }
      ]
    }))
}

// 10. 配置一个监控任务
// 作用: src 内的代码一旦改变, 那么实时从新打包更新 dist 内的代码
const watchHandler = () => {
  // 利用 gulp.watch() 方法, 来实现
  gulp.watch('./src/views/*.html', htmlHandler)
  gulp.watch('./src/css/*.css', cssHandler)
}



// end. 创建一个默认任务
// 作用: 统一分配这些任务的执行
// 把以上的所有任务同时开始执行
// gulp 设置多个任务同时开始, 使用语法:
//   语法: gulp.parallel(任务1, 任务2, 任务3, ...)
//   返回值: 就是一个函数
// 不要忘了把这个任务导出
// 注意: 建议你导出的时候, 叫做 default
// 当你在命令行执行 gulp default 的时候, 可以简写成 gulp
// 当你什么都不写的时候, 默认执行一个叫做 default 的任务
// const _default = gulp.parallel(cssHandler, sassHandler, htmlHandler, jsHandler, imgHandler, videoHandler, audioHandler, fontHandler)

// 把 delHandler 也加入到 默认任务队列中
// gulp 设置多个任务逐个开始, 使用语法:
//   语法: gulp.series(任务1, 任务2, 任务3, ...)
//   返回值: 就是一个函数
const _default = gulp.series(
  delHandler,
  gulp.parallel(cssHandler, sassHandler, htmlHandler, jsHandler, imgHandler, videoHandler, audioHandler, fontHandler),
  serverHandler,
  watchHandler
)

// 要在当前文件内对书写好的 任务函数进行导出
module.exports = {
  cssHandler,
  sassHandler,
  jsHandler,
  htmlHandler,
  imgHandler,
  videoHandler,
  audioHandler,
  fontHandler,
  delHandler,
  default: _default
}
